package cn.org.xiaosheng.common.config;

import cn.org.xiaosheng.service.CacheService;
import cn.org.xiaosheng.service.impl.CacheServiceImpl;
import com.github.benmanes.caffeine.cache.*;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 因为Caffeine与Guave Cache都是出自于Google，并且前者是在后者基础上进行改写的，所以代码API上差不了多少
 */
@Configuration
public class CaffeineCacheConfig {

    public static CacheService cacheService() {
        return new CacheServiceImpl();
    }

    /**
     * 移除监听器
     * new RemovalListener<String, String>() {
     *                 @Override
     *                 public void onRemoval(String key, String value, RemovalCause cause) {
     *                     System.out.println("Key " + key + " was removed (" + cause + ")");
     *                 }
     *             }
     */


    private static final Cache<String, String> cache= Caffeine.newBuilder()
        //初始数量
        .initialCapacity(10)
        //最大条数
        .maximumSize(10)
        //expireAfterWrite和expireAfterAccess同时存在时，以expireAfterWrite为准
        //最后一次写操作后经过指定时间过期
        .expireAfterWrite(100,TimeUnit.SECONDS)
        //最后一次读或写操作后经过指定时间过期
        .expireAfterAccess(100, TimeUnit.SECONDS)
        //监听缓存被移除
        .removalListener(new RemovalListener<String, String>() {
            @Override
            public void onRemoval(@Nullable String key, @Nullable String value, RemovalCause removalCause) {
                System.out.println("Key: " + key + "Value: " + value + "Cause:" + removalCause);
            }
        })
            //记录命中
        .recordStats()
        .build();

    private static final LoadingCache<String, String> LoadingCache = Caffeine.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build(new CacheLoader<String, String>() {
                @Override
                public String load(String key) {
                    return cacheService().getDataFromDatabase(key);
                }
            });

    private static final AsyncCache<String,String> asyncCache=Caffeine.newBuilder()
            //创建缓存或者最近一次更新缓存后经过指定时间间隔刷新缓存；仅支持LoadingCache
            .refreshAfterWrite(1,TimeUnit.SECONDS)
            .expireAfterWrite(1,TimeUnit.SECONDS)
            .expireAfterAccess(1,TimeUnit.SECONDS)
            .maximumSize(10)
            //根据key查询数据库里面的值
            .buildAsync(key->{
                Thread.sleep(1000);
                String dataFromDatabase = cacheService().getDataFromDatabase(key);
                return dataFromDatabase;
            });


    private static final AsyncLoadingCache<String,String> asyncLoadingCache=Caffeine.newBuilder()
            //创建缓存或者最近一次更新缓存后经过指定时间间隔刷新缓存；仅支持LoadingCache
            .refreshAfterWrite(1,TimeUnit.SECONDS)
            .expireAfterWrite(1,TimeUnit.SECONDS)
            .expireAfterAccess(1,TimeUnit.SECONDS)
            .maximumSize(10)
            //根据key查询数据库里面的值
            .buildAsync(key->{
                Thread.sleep(1000);
                String dataFromDatabase = cacheService().getDataFromDatabase(key);
                return dataFromDatabase;
            });

        //异步缓存返回的是CompletableFuture
        CompletableFuture<String> future=asyncLoadingCache.get("1");


    @Bean
    public Cache caffeineCache() {
        return cache;
    }

    @Bean
    public LoadingCache caffeineLoadingCache() {
        return LoadingCache;
    }

    @Bean
    public AsyncLoadingCache asyncLoadingCache() {
        return asyncLoadingCache;
    }

    @Bean
    public AsyncCache asyncCache() {
        return asyncCache;
    }

}

